<template>
	<view class="content">
		<view class="close" @tap="closeCalculatorPopup">x</view>
		<scroll-view scroll-y="true" class="view">
			<span>
				{{ formatt(viewValue) }}
			</span>
		</scroll-view>
	<!-- 按钮 -->
	<view class="btns" @click="handleClick">
		<view v-for="item in btns" :key='item.text' :class="item.className" :data-text="item.text"></view>
	</view>
</view>

</template>
<!-- <script>
import { KEYS, symbolReg1, symbolReg2, symbolReg3, operation, computeCount } from './utils';
// 计算逻辑
let computes = []
// 存储最后操作符 0 为操作符，1为值
let cacheLastSymbol = []

// 乘除运算符次数
let countSymbol1 = 0
// 加减
let countSymbol2 = 0

// 修改状态 0 不需要操作栈，1删除栈中倒数第二个符号自身、上一个以及下一个下标，2删除倒数第一个符号之前的栈，使用viewValue代替
let editStatus = 0

// 判断最后一个是否为计算符号
const isSymbol = () => {
	return symbolReg3.test(computes[computes.length - 1])
}

/**
 * 计算逻辑
 * @param {string} type 0加减 1乘除
 * @param {number} count 次数
 * @returns string
 * */
const numFun = (type, count) => {
	let num = undefined
	for (let i = 1; i <= count; i++) {
		// 乘除号下标, 3、7下标除、乘
		console.log(computes, 'numFun');
		const index = computes.findIndex(symbol => type === '0' ? symbolReg2.test(symbol) : symbolReg1.test(symbol))
		if (index == -1) return
		// 进行计算
		// 这里可以使用 eval将字符串当做js执行, 需要去判断 *
		if (index === computes.length - 1) { // 如果最后一个是字符而非数字的情况
			computes.splice(index - 1, 2, operation(computes[index - 1], computes[index - 1], computes[index]))
		} else {
			computes.splice(index - 1, 3, operation(computes[index - 1], computes[index + 1], computes[index]))
		}

		// 等于二说明最后是字符。这里匹配多个操作符时运算, count == 1时，栈中之后存在一个值
		if (isSymbol()) {
			cacheLastSymbol[1] = computes[computes.length - 2]
		}
	}
}

export default {
	data() {
		return {
			// 渲染值
			viewValue: 0,
			btns: KEYS && KEYS.map(item => {
				let className = 'default'

				// 相同类型的添加 class
				if (symbolReg3.test(item) || item === KEYS[KEYS.length - 1]) {
					className = 'origin'
				}
				if (new RegExp(`${KEYS[0]}|(?=${KEYS[1]})|${KEYS[2]}`).test(item)) {
					className = 'gray'
				}

				// 单独区分样式
				if (item === '0') {
					className = 'zero'
				}

				return {
					text: item,
					className
				}
			})
		}
	},
	methods: {
		closeCalculatorPopup() {
			this.viewValue = 0
			computes = []
			cacheLastSymbol = []
			this.$emit('closeCalculatorPopup');
		},
		handleClick({ target }) {
			if (target.dataset.text == undefined) return

			switch (target.dataset.text) {
				// AC 点击
				case this.btns[0].text:
					this.btns[0].text = KEYS[0]
					this.viewValue = 0
					cacheLastSymbol = []
					countSymbol1 = 0
					countSymbol2 = 0
					computes = []
					break;
				// 加减乘除点击
				case KEYS[4 - 1]:
				case KEYS[2 * 4 - 1]:
				case KEYS[3 * 4 - 1]:
				case KEYS[4 * 4 - 1]:
					// 不能一开始就是符号
					if (computes.length == 0) return

					if (isSymbol()) {
						// 改变符号
						computes[computes.length - 1] = target.dataset.text
					} else {
						computes.push(target.dataset.text)
						// 加入统计字符
						if (symbolReg1.test(target.dataset.text)) countSymbol1++
						if (symbolReg2.test(target.dataset.text)) countSymbol2++
					}

					if (computes.length > 3) {
						const previousSymbolIndex = computes.length - 3
						// 判断上一个符号是否是乘除 && 当前符号为加减
						if (symbolReg1.test(computes[previousSymbolIndex]) && symbolReg2.test(target.dataset.text)) {

							this.viewValue = computeCount([...computes])
							// console.log('上个乘除当前符号加减', this.viewValue);
							editStatus = 2
						}
						// 上个符号和当前符号 一样的类型
						if (
							(symbolReg1.test(computes[previousSymbolIndex]) && symbolReg1.test(target.dataset.text)) ||
							(symbolReg2.test(computes[previousSymbolIndex]) && symbolReg2.test(target.dataset.text))
						) {
							// console.log('符号相同');
							this.viewValue = operation(computes[previousSymbolIndex - 1], computes[previousSymbolIndex + 1], computes[previousSymbolIndex])
							editStatus = 1
						}

						if (!editStatus) {
							this.viewValue = computes[computes.length - 2]
							editStatus = 0
						}
					}

					break;
				// 等于
				case KEYS[KEYS.length - 1]:
					//  if (cacheLastSymbol.length == 2) { // 第一次计算结束
					//  	computes[0] = operation(computes[0], cacheLastSymbol[1], cacheLastSymbol[0])
					//  }
					//  if (countSymbol1 || countSymbol2) { // 存在操作符时，将操作符加入缓存变量
					//  	if (isSymbol()) { // 判断最后一个是操作符则取操作符前一个
					//  		cacheLastSymbol[0] = computes[computes.length - 1]
					//  		cacheLastSymbol[1] = computes[computes.length - 2]
					//  	} else {
					//  		cacheLastSymbol[0] = computes[computes.length - 2]
					//  		cacheLastSymbol[1] = computes[computes.length - 1]
					//  	}
					//  }
					
					//  if (countSymbol1) numFun('1', countSymbol1)
					//  if (countSymbol2) numFun('0', countSymbol2)
					
					//  // 清除操作符统计
					//  countSymbol1 = 0
					//  countSymbol2 = 0
					//  if (computes.length == 1) {
					//  	this.viewValue = computes[0]
					//  }
					if (!(computes[0] && computes[2] && computes[1])) {
						return;
					}
					let thisValue =parseFloat(operation(computes[0], computes[2], computes[1]).toFixed(6))
					// if (BigInt(thisValue)?.toString()?.length > 21) {
					//   return notificationFun('数值过大！')
					// }
					this.viewValue = thisValue
					break;
				// 取反
				case KEYS[1]:
					// 兼容-0的情况
					if (this.viewValue === '-0') {
						this.viewValue = 0
					} else {
						this.viewValue = this.viewValue >= 0 ? '-' + this.viewValue : Math.abs(this.viewValue)
					}
					if (computes.length == 1) {
						computes[0] = this.viewValue
					} else {
						const lastIndex = computes.lastIndexOf(this.viewValue)
						computes.splice(lastIndex, 1, this.viewValue)
					}
					break;
				// 百分号
				case KEYS[2]:
					this.viewValue = this.viewValue * 0.01
					if (computes.length == 1) {
						computes[0] = this.viewValue
					} else {
						const lastIndex = computes.lastIndexOf(this.viewValue)
						computes.splice(lastIndex, 1, this.viewValue)
					}
					break;
				// 数字
				default:
					// if (this.viewValue.length > (String(this.viewValue).indexOf('.') !== -1 ? 16 : 16)) {
					// 	return notificationFun('数值过大！')
					// }
					console.log(this.viewValue,'viewValue',computes)
					if (editStatus) { 
						if (editStatus === 1) {
							const previousSymbolIndex = computes.length - 3
							computes.splice(previousSymbolIndex - 1, 3, operation(computes[previousSymbolIndex - 1], computes[previousSymbolIndex + 1], computes[previousSymbolIndex]))
						}
						if (editStatus === 2) computes.splice(0, computes.length - 1, this.viewValue)
						editStatus = 0
					}

					if (isSymbol()) {
						this.viewValue = target.dataset.text
						computes.push(this.viewValue)
					} else {
						// 判断是否存在 .
						if (String(this.viewValue).indexOf('.') != -1 && target.dataset.text === '.') {
							return
						}
						// 三元判断是否为点,避免 Number(.) 会为NaN
						this.viewValue += this.viewValue === 0
							? target.dataset.text !== '.' ? Number(target.dataset.text) : target.dataset.text
							: target.dataset.text
						computes[computes.length > 0 ? computes.length - 1 : 0] = this.viewValue
					}

					this.btns[0].text = computes.length > 0 || this.viewValue > 0 ? 'C' : KEYS[0]
			}
		},
		// 格式化
		formatt(val) {
			return val.toString()
		}
	}
}
</script> -->
<script>
import { KEYS, symbolReg1, symbolReg2, symbolReg3, operation, computeCount } from './utils';

// 计算逻辑
let computes = []
// 存储最后操作符 0 为操作符，1为值
let cacheLastSymbol = []

// 乘除运算符次数
let countSymbol1 = 0
// 加减
let countSymbol2 = 0

// 修改状态 0 不需要操作栈，1删除栈中倒数第二个符号自身、上一个以及下一个下标，2删除倒数第一个符号之前的栈，使用viewValue代替
let editStatus = 0

// 当前计算结果
let currentResult = 0

// 判断最后一个是否为计算符号
const isSymbol = () => {
	return symbolReg3.test(computes[computes.length - 1])
}

/**
 * 计算逻辑
 * @param {string} type 0加减 1乘除
 * @param {number} count 次数
 * @returns string
 * */
const numFun = (type, count) => {
	let num = undefined
	for (let i = 1; i <= count; i++) {
		// 乘除号下标, 3、7下标除、乘
		console.log(computes, 'numFun');
		const index = computes.findIndex(symbol => type === '0' ? symbolReg2.test(symbol) : symbolReg1.test(symbol))
		if (index == -1) return
		// 进行计算
		// 这里可以使用 eval将字符串当做js执行, 需要去判断 *
		if (index === computes.length - 1) { // 如果最后一个是字符而非数字的情况
			computes.splice(index - 1, 2, operation(computes[index - 1], computes[index - 1], computes[index]))
		} else {
			computes.splice(index - 1, 3, operation(computes[index - 1], computes[index + 1], computes[index]))
		}

		// 等于二说明最后是字符。这里匹配多个操作符时运算, count == 1时，栈中之后存在一个值
		if (isSymbol()) {
			cacheLastSymbol[1] = computes[computes.length - 2]
		}
	}
}

export default {
	data() {
		return {
			// 渲染值
			viewValue: 0,
			btns: KEYS && KEYS.map(item => {
				let className = 'default'

				// 相同类型的添加 class
				if (symbolReg3.test(item) || item === KEYS[KEYS.length - 1]) {
					className = 'origin'
				}
				if (new RegExp(`${KEYS[0]}|(?=${KEYS[1]})|${KEYS[2]}`).test(item)) {
					className = 'gray'
				}

				// 单独区分样式
				if (item === '0') {
					className = 'zero'
				}

				return {
					text: item,
					className
				}
			})
		}
	},
	methods: {
		closeCalculatorPopup() {
			this.viewValue = 0
			computes = []
			cacheLastSymbol = []
			currentResult = 0
			this.$emit('closeCalculatorPopup');
		},
		handleClick({ target }) {
			if (target.dataset.text == undefined) return

			switch (target.dataset.text) {
				// AC 点击
				case this.btns[0].text:
					this.btns[0].text = KEYS[0]
					this.viewValue = 0
					cacheLastSymbol = []
					countSymbol1 = 0
					countSymbol2 = 0
					computes = []
					currentResult = 0
					break;
				// 加减乘除点击
				case KEYS[4 - 1]:
				case KEYS[2 * 4 - 1]:
				case KEYS[3 * 4 - 1]:
				case KEYS[4 * 4 - 1]:
					// 不能一开始就是符号
					if (computes.length == 0) return

					if (isSymbol()) {
						// 改变符号
						computes[computes.length - 1] = target.dataset.text
					} else {
						computes.push(target.dataset.text)
						// 加入统计字符
						if (symbolReg1.test(target.dataset.text)) countSymbol1++
						if (symbolReg2.test(target.dataset.text)) countSymbol2++
					}

					if (computes.length > 3) {
						const previousSymbolIndex = computes.length - 3
						// 判断上一个符号是否是乘除 && 当前符号为加减
						if (symbolReg1.test(computes[previousSymbolIndex]) && symbolReg2.test(target.dataset.text)) {

							this.viewValue = computeCount([...computes])
							// console.log('上个乘除当前符号加减', this.viewValue);
							editStatus = 2
						}
						// 上个符号和当前符号 一样的类型
						if (
							(symbolReg1.test(computes[previousSymbolIndex]) && symbolReg1.test(target.dataset.text)) ||
							(symbolReg2.test(computes[previousSymbolIndex]) && symbolReg2.test(target.dataset.text))
						) {
							// console.log('符号相同');
							this.viewValue = operation(computes[previousSymbolIndex - 1], computes[previousSymbolIndex + 1], computes[previousSymbolIndex])
							editStatus = 1
						}

						if (!editStatus) {
							this.viewValue = computes[computes.length - 2]
							editStatus = 0
						}
					}

					break;
				// 等于
				case KEYS[KEYS.length - 1]:
					//  if (cacheLastSymbol.length == 2) { // 第一次计算结束
					//  	computes[0] = operation(computes[0], cacheLastSymbol[1], cacheLastSymbol[0])
					//  }
					//  if (countSymbol1 || countSymbol2) { // 存在操作符时，将操作符加入缓存变量
					//  	if (isSymbol()) { // 判断最后一个是操作符则取操作符前一个
					//  		cacheLastSymbol[0] = computes[computes.length - 1]
					//  		cacheLastSymbol[1] = computes[computes.length - 2]
					//  	} else {
					//  		cacheLastSymbol[0] = computes[computes.length - 2]
					//  		cacheLastSymbol[1] = computes[computes.length - 1]
					//  	}
					//  }
					
					//  if (countSymbol1) numFun('1', countSymbol1)
					//  if (countSymbol2) numFun('0', countSymbol2)
					
					//  // 清除操作符统计
					//  countSymbol1 = 0
					//  countSymbol2 = 0
					//  if (computes.length == 1) {
					//  	this.viewValue = computes[0]
					//  }
					if (!(computes[0] && computes[2] && computes[1])) {
						return;
					}
					let thisValue =parseFloat(operation(computes[0], computes[2], computes[1]).toFixed(6))
					// if (BigInt(thisValue)?.toString()?.length > 21) {
					//   return notificationFun('数值过大！')
					// }
					this.viewValue = thisValue
					currentResult = thisValue
					computes = [thisValue] // 将计算结果作为新的初始值
					break;
				// 取反
				case KEYS[1]:
					// 兼容-0的情况
					if (this.viewValue === '-0') {
						this.viewValue = 0
					} else {
						this.viewValue = this.viewValue >= 0 ? '-' + this.viewValue : Math.abs(this.viewValue)
					}
					if (computes.length == 1) {
						computes[0] = this.viewValue
					} else {
						const lastIndex = computes.lastIndexOf(this.viewValue)
						computes.splice(lastIndex, 1, this.viewValue)
					}
					break;
				// 百分号
				case KEYS[2]:
					this.viewValue = this.viewValue * 0.01
					if (computes.length == 1) {
						computes[0] = this.viewValue
					} else {
						const lastIndex = computes.lastIndexOf(this.viewValue)
						computes.splice(lastIndex, 1, this.viewValue)
					}
					break;
				// 数字
				default:
					// if (this.viewValue.length > (String(this.viewValue).indexOf('.') !== -1 ? 16 : 16)) {
					// 	return notificationFun('数值过大！')
					// }
					console.log(this.viewValue,'viewValue',computes)
					if (editStatus) { 
						if (editStatus === 1) {
							const previousSymbolIndex = computes.length - 3
							computes.splice(previousSymbolIndex - 1, 3, operation(computes[previousSymbolIndex - 1], computes[previousSymbolIndex + 1], computes[previousSymbolIndex]))
						}
						if (editStatus === 2) computes.splice(0, computes.length - 1, this.viewValue)
						editStatus = 0
					}

					if (isSymbol()) {
						this.viewValue = target.dataset.text
						computes.push(this.viewValue)
					} else {
						// 判断是否存在 .
						if (String(this.viewValue).indexOf('.') != -1 && target.dataset.text === '.') {
							return
						}
						// 三元判断是否为点,避免 Number(.) 会为NaN
						this.viewValue += this.viewValue === 0
							? target.dataset.text !== '.' ? Number(target.dataset.text) : target.dataset.text
							: target.dataset.text
						computes[computes.length > 0 ? computes.length - 1 : 0] = this.viewValue
					}

					this.btns[0].text = computes.length > 0 || this.viewValue > 0 ? 'C' : KEYS[0]
			}
		},
		// 格式化
		formatt(val) {
			return val.toString()
		}
	}
}
</script>
<style scoped lang="scss">
.content {
	width: 100%;
	height: 100%;
	display: flex;
	flex-wrap: wrap;
	align-content: flex-end;
	background: #DEDEDE;
	box-sizing: border-box;
	font-family: PingFangSC-Regular, sans-serif;
	border-radius: 16rpx;
	overflow: hidden;

	>view {
		width: 100%;
		color: #ffffff;
	}

	.close {
		position: absolute;
		z-index: 9999;
		right: 40rpx;
		//   top: 20rpx;
		width: 32rpx;
		height: 32rpx;
		border-radius: 16rpx;
		background: #FF4D00;
		color: #FFF;
		text-align: center;
		line-height: 32rpx;
		font-size: 26rpx;
	}

	.view {
		text-align: right;
		font-size: 88rpx;
		line-height: 88rpx;
		color: #333;
		width: 100%;
		height: 300rpx;
		word-break: break-all;
		white-space: normal;
		padding-top: 50rpx;

		>.lessen {
			font-size: 138rpx;
		}

		>span {
			display: inline-block;

			box-sizing: border-box;
			-webkit-user-select: text;
			-moz-user-select: text;
			-ms-user-select: text;
			user-select: text;
			overflow: hidden;
			border-radius: 20rpx;

			&::selection {
				background-color: #333;
				color: #fff;
			}
		}
	}

	.btns {
		width: 100%;
		display: flex;
		flex-direction: row;
		flex-wrap: wrap;
		justify-content: space-between;
		background: #FAFAFA;
		padding: 20rpx;
		border-radius: 16rpx;

		>view {
			width: calc(100% / 4 - 20rpx);
			height: 128rpx;
			border-radius: 16rpx;
			box-sizing: border-box;
			display: flex;
			align-items: center;
			justify-content: center;
			font-size: 60rpx;
			color: #585858;
			box-shadow: 0 8rpx 12rpx rgba(0, 0, 0, 0.1);
			transition: all .3s;
			background: linear-gradient(180deg, #717171 0%, #505050 102.5%);
			margin: 15rpx 10rpx;

			&.zero {
				background: linear-gradient(180deg, #FFFFFF 0%, #ECECEC 102.5%);
				width: calc(100% / 4 * 2 - 20rpx);
			}

			&.origin {
				background: #FF8A00;
				color: #FFFFFF;

				&:active {
					background: #ffffff;
					color: #FF8A00;
				}
			}

			&.gray {
				background: linear-gradient(180deg, #717171 0%, #505050 102.5%);
				color: #FFFFFF;

				&:active {
					background: #eeeeee;
				}
			}

			&.default {
				background: linear-gradient(180deg, #FFFFFF 0%, #ECECEC 102.5%);

				&:active {
					background: #bbbbbb;
				}
			}

			&::after {
				content: attr(data-text);
			}
		}
	}
}
</style>